package com.tencent.libpag.sample.libpag_sample

import android.graphics.BitmapFactory
import android.media.MediaMuxer
import android.opengl.*
import android.os.Bundle
import android.os.Environment
import androidx.appcompat.app.AppCompatActivity
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.RelativeLayout
import androidx.lifecycle.lifecycleScope
import com.socks.library.KLog
import com.tencent.libpag.sample.libpag_sample.codec.MediaEncodeManager
import com.tencent.libpag.sample.libpag_sample.codec.MediaMuxerChangeListener
import com.tencent.libpag.sample.libpag_sample.codec.MuxerStatus
import com.tencent.libpag.sample.libpag_sample.test.EncodeAndMuxTest
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.libpag.*
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {
    private var eglDisplay: EGLDisplay? = null
    private var eglSurface: EGLSurface? = null
    private var eglContext: EGLContext? = null

    private val TAG = "MainActivity"

    @Synchronized
    private fun eglSetup() {
        eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
        val version = IntArray(2)
        EGL14.eglInitialize(eglDisplay, version, 0, version, 1)
        EGL14.eglBindAPI(EGL14.EGL_OPENGL_ES_API)
        val attributeList = intArrayOf(
                EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
                EGL14.EGL_RED_SIZE, 8,
                EGL14.EGL_GREEN_SIZE, 8,
                EGL14.EGL_BLUE_SIZE, 8,
                EGL14.EGL_ALPHA_SIZE, 8,
                EGL14.EGL_STENCIL_SIZE, 8,
                EGL14.EGL_SAMPLE_BUFFERS, 1,
                EGL14.EGL_SAMPLES, 4,
                EGL14.EGL_NONE
        )
        val configs = arrayOfNulls<EGLConfig>(1)
        val numConfigs = IntArray(1)
        EGL14.eglChooseConfig(eglDisplay, attributeList, 0, configs, 0,
                configs.size, numConfigs, 0)
        val attribute_list = intArrayOf(
                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL14.EGL_NONE
        )
        eglContext = EGL14.eglCreateContext(eglDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
                attribute_list, 0)
        val surfaceAttributes = intArrayOf(
                EGL14.EGL_WIDTH, 1,
                EGL14.EGL_HEIGHT, 1,
                EGL14.EGL_NONE
        )
        eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, configs[0], surfaceAttributes, 0)
        EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)
    }

    private val magic = Environment.getExternalStoragePublicDirectory("magic")


    private fun createPAGImage(): PAGImage? {
//        eglSetup();
        val assetManager = assets
        var stream: InputStream? = null
        try {
            stream = assetManager.open("test.png")
        } catch (e: IOException) {
            e.printStackTrace()
        }
        val bitmap = BitmapFactory.decodeStream(stream) ?: return null
        return PAGImage.FromBitmap(bitmap)

//        int[] textures = new int[1];
//        GLES20.glGenTextures(1, textures, 0);
//        int textureID = textures[0];
//        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
//        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
//            GLES20.GL_LINEAR);
//        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
//            GLES20.GL_LINEAR);
//        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
//            GLES20.GL_CLAMP_TO_EDGE);
//        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
//            GLES20.GL_CLAMP_TO_EDGE);
//        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, bitmap.getWidth(),
//            bitmap.getHeight(), 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
//        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
//
//        return PAGImage.FromTexture(textureID, GLES20.GL_TEXTURE_2D,
//            bitmap.getWidth(), bitmap.getHeight());
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
        setContentView(R.layout.activity_main)
        val backgroundView = findViewById<RelativeLayout>(R.id.background_view)
        val pagView = PAGView(this, eglContext)
        pagView.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        backgroundView.addView(pagView)

        if (!magic.exists()) {
            magic.mkdirs()
        }
        val pagFile = PAGFile.Load(assets, "main.pag")

        tv?.text = "${pagFile?.path()}"

  /*      testReplaceImage(pagFile, pagView)
        testEditText(pagFile, pagView)
        pagView.setRepeatCount(-1)
        pagView.file = pagFile
        pagView.play()*/

        btnGenerateVideo?.setOnClickListener {

            lifecycleScope.launch(Dispatchers.IO) {
                generateVideo(pagFile)

            }

        }

        val test = EncodeAndMuxTest()
        btnEgl?.setOnClickListener {
            lifecycleScope.launch(Dispatchers.IO){
                test.testEncodeVideoToMp4(pagFile)

            }

        }
    }

    /**
     * Test replace image.
     */
    fun testReplaceImage(pagFile: PAGFile?, pagView: PAGView?) {
        if (pagFile == null || pagView == null || pagFile.numImages() <= 0) return
        pagView.replaceImage(0, createPAGImage())
    }

    /**
     *
     * Test edit text.
     */
    fun testEditText(pagFile: PAGFile?, pagView: PAGView?) {
        if (pagFile == null || pagView == null || pagFile.numTexts() <= 0) return
        val textData = pagFile.getTextData(0)
        textData.text = "haha哈哈大😆"
        textData.fontSize = 13f
        pagView.setTextData(0, textData)
    }

    private fun generateVideo(pagFile: PAGFile?) {
        pagFile ?: return
        val name = File(pagFile.path()).name
        val width: Int = pagFile.width()
        val height: Int = pagFile.height()
        val duration = (pagFile.duration() / 1000000).toInt()
        val FRAME_RATE = pagFile.frameRate().toInt()
        val NUM_FRAMES = (duration * FRAME_RATE)
        KLog.e(TAG, "(FRAME_RATE fps)$FRAME_RATE x (duration s)$duration =(NUM_FRAMES) $NUM_FRAMES ")
        val currentDate = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA).format(Date())
        val outputPath = File(magic, name.substring(0, name.lastIndexOf(".")) + "-${width}x${height}.mp4").toString()
        KLog.e(TAG, "$currentDate output file is $outputPath")


        val mediaFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4
        //String audioType = MediaFormat.MIMETYPE_AUDIO_AAC;
        val audioType = "audio/mp4a-latm"
        //String videoType = MediaFormat.MIMETYPE_VIDEO_AVC;
        val videoType = "video/avc"
        val sampleRate = 44100
        val channelCount = 2 //单声道 channelCount=1 , 双声道  channelCount=2
        //AudioCapture.class类中采集音频采用的位宽：AudioFormat.ENCODING_PCM_16BIT ，此处应传入16bit，
        // 用作计算pcm一帧的时间戳
        val audioFormat = 16
        //预览
        val pagPlayer = PAGPlayer()

        val mediaEncodeManager = MediaEncodeManager()


        mediaEncodeManager.initMediaCodec(outputPath, mediaFormat, audioType, sampleRate,
                channelCount, audioFormat, videoType, width, height, FRAME_RATE)
        mediaEncodeManager.initThread(object : MediaMuxerChangeListener {
            override fun onMediaMuxerChangeListener(status: MuxerStatus) {
                when (status) {
                    MuxerStatus.MUXER_START -> {
                        runOnUiThread {
                            tv?.text = "开始编码"
                        }
                        KLog.e(TAG, "开始编码😆")
                    }

                    MuxerStatus.MUXER_STOP -> {
                        runOnUiThread {
                            tv?.text = "编码完成 ==> $outputPath"
                        }
                        KLog.e(TAG, "编码完成 $outputPath")
                    }
                }

            }

            override fun onMediaInfoListener(time: Int) {
                runOnUiThread {
                    tv?.text = "编码时长:$time"
                }
                KLog.e(TAG, "onMediaInfoListener : $time")
            }
        })
        val pagSurface = PAGSurface.FromSurface(mediaEncodeManager.surface)
        pagPlayer.surface = pagSurface
        pagPlayer.composition = pagFile
        mediaEncodeManager.startEncode()
        repeat(NUM_FRAMES) {
            val progress = it / NUM_FRAMES.toDouble()
            pagPlayer.progress = progress
            pagPlayer.flush()
        }
        mediaEncodeManager.stopEncode()


    }
}